package com.paziy.jan.calc.expressions;

import com.paziy.jan.calc.literals.Computable;
import com.paziy.jan.calc.literals.Literal;
import com.paziy.jan.calc.literals.numbers.Num;

import com.paziy.jan.calc.literals.operations.exeptions.*;
import java.util.*;


public class ReversePolishNotation {  //ReversePolishNotation


    private Collection<Literal> collection;

    ReversePolishNotation() {
        collection = new ArrayList<Literal>();
    }

    ReversePolishNotation(Collection<Literal> collection) {
        this.collection = collection;
    }

    public boolean add(Literal element) {
        return collection.add(element);
    }

    public Num evaluate() throws Exception {

        Iterator<Literal> iterator = collection.iterator();

        LinkedList<Num> stack = new LinkedList<Num>();

        while(iterator.hasNext()){

            Literal el = iterator.next();

            if(el instanceof Num) {
                stack.push((Num) el);
                continue;
            }

            if(el instanceof Computable) {
                Computable operation = (Computable) el;

                LinkedList<Num> operands = new LinkedList<Num>();
                
                for(byte i = 1; operation.getCountOperands() >= i; ++i ) {
                    operands.push(stack.pop());
                }

                stack.push(operation.apply(operands));
            }
        }

        return stack.pop();
    }
}
